use std::sync::Arc;
use anyhow::Result;

use crate::di::{AppContainer, ServiceContainer};
use crate::di::services::*;
use crate::config::{Configs, Server, DataBase, Log, Jwt, Cert};

/// 创建测试配置
fn create_test_config() -> Configs {
    Configs {
        server: Server {
            name: "integration-test-server".to_string(),
            address: "127.0.0.1:9999".to_string(),
            ssl: false,
        },
        database: DataBase {
            database_url: "sqlite::memory:".to_string(),
        },
        log: Log {
            filter_level: "debug".to_string(),
            with_ansi: false,
            to_stdout: false,
            directory: "./test-logs".to_string(),
            file_name: "integration-test.log".to_string(),
            rolling: "never".to_string(),
        },
        jwt: Jwt {
            jwt_secret: "integration_test_secret".to_string(),
            jwt_exp: 7200,
        },
        cert: Cert {
            cert: "integration-test.pem".to_string(),
            key: "integration-test.key".to_string(),
        },
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[tokio::test]
    async fn test_dependency_injection_integration() {
        // 创建一个独立的容器进行测试
        let container = ServiceContainer::new();
        let config = create_test_config();
        
        // 注册配置服务
        container.register_singleton::<ConfigService, _>({
            let config = config.clone();
            move |_| Ok(ConfigService::new(config.clone()))
        }).unwrap();
        
        // 测试配置服务解析
        let config_service = container.resolve::<ConfigService>().unwrap();
        assert_eq!(config_service.config().server.name, "integration-test-server");
        assert_eq!(config_service.config().server.address, "127.0.0.1:9999");
        assert_eq!(config_service.config().jwt.jwt_secret, "integration_test_secret");
    }

    #[tokio::test]
    async fn test_service_chain_resolution() {
        let container = ServiceContainer::new();
        let config = create_test_config();
        
        // 注册配置服务
        container.register_singleton::<ConfigService, _>({
            let config = config.clone();
            move |_| Ok(ConfigService::new(config.clone()))
        }).unwrap();
        
        // 注册一个模拟的数据库服务（不需要真实的数据库连接）
        container.register_singleton::<MockDatabaseService, _>(|_| {
            Ok(MockDatabaseService::new())
        }).unwrap();
        
        // 注册扩展存储服务
        container.register_singleton::<MockExtensionStoreService, _>(|container| {
            let db_service = container.resolve::<MockDatabaseService>()?;
            Ok(MockExtensionStoreService::new(db_service))
        }).unwrap();
        
        // 注册角色服务
        container.register_singleton::<MockRoleService, _>(|container| {
            let store_service = container.resolve::<MockExtensionStoreService>()?;
            Ok(MockRoleService::new(store_service))
        }).unwrap();
        
        // 注册用户服务
        container.register_singleton::<MockUserService, _>(|container| {
            let store_service = container.resolve::<MockExtensionStoreService>()?;
            let role_service = container.resolve::<MockRoleService>()?;
            let config_service = container.resolve::<ConfigService>()?;
            Ok(MockUserService::new(store_service, role_service, config_service))
        }).unwrap();
        
        // 测试整个服务链的解析
        let user_service = container.resolve::<MockUserService>().unwrap();
        assert_eq!(user_service.get_server_name(), "integration-test-server");
    }

    #[tokio::test]
    async fn test_concurrent_service_resolution() {
        use tokio::task;
        
        let container = Arc::new(ServiceContainer::new());
        let config = create_test_config();
        
        // 注册服务
        container.register_singleton::<ConfigService, _>({
            let config = config.clone();
            move |_| Ok(ConfigService::new(config.clone()))
        }).unwrap();
        
        // 创建多个并发任务
        let mut handles = Vec::new();
        for i in 0..20 {
            let container_clone = Arc::clone(&container);
            let handle = task::spawn(async move {
                // 每个任务都尝试解析服务
                let config_service = container_clone.resolve::<ConfigService>().unwrap();
                assert_eq!(config_service.config().server.name, "integration-test-server");
                
                // 模拟一些工作
                tokio::time::sleep(tokio::time::Duration::from_millis(10)).await;
                
                // 再次解析，应该得到同一个实例
                let config_service2 = container_clone.resolve::<ConfigService>().unwrap();
                assert!(Arc::ptr_eq(&config_service, &config_service2));
                
                i
            });
            handles.push(handle);
        }
        
        // 等待所有任务完成
        for handle in handles {
            handle.await.unwrap();
        }
    }

    #[tokio::test]
    async fn test_service_lifecycle() {
        let container = ServiceContainer::new();
        
        // 注册单例服务
        container.register_singleton::<TestSingletonService, _>(|_| {
            Ok(TestSingletonService::new("singleton"))
        }).unwrap();
        
        // 注册瞬态服务
        container.register_transient::<TestTransientService, _>(|_| {
            Ok(TestTransientService::new("transient"))
        }).unwrap();
        
        // 测试单例行为
        let singleton1 = container.resolve::<TestSingletonService>().unwrap();
        let singleton2 = container.resolve::<TestSingletonService>().unwrap();
        assert!(Arc::ptr_eq(&singleton1, &singleton2));
        
        // 测试瞬态行为
        let transient1 = container.resolve::<TestTransientService>().unwrap();
        let transient2 = container.resolve::<TestTransientService>().unwrap();
        assert!(!Arc::ptr_eq(&transient1, &transient2));
    }

    // 测试用的模拟服务
    #[derive(Debug)]
    struct MockDatabaseService {
        name: String,
    }
    
    impl MockDatabaseService {
        fn new() -> Self {
            Self {
                name: "mock-database".to_string(),
            }
        }
    }
    
    #[derive(Debug)]
    struct MockExtensionStoreService {
        db_service: Arc<MockDatabaseService>,
    }
    
    impl MockExtensionStoreService {
        fn new(db_service: Arc<MockDatabaseService>) -> Self {
            Self { db_service }
        }
    }
    
    #[derive(Debug)]
    struct MockRoleService {
        store_service: Arc<MockExtensionStoreService>,
    }
    
    impl MockRoleService {
        fn new(store_service: Arc<MockExtensionStoreService>) -> Self {
            Self { store_service }
        }
    }
    
    #[derive(Debug)]
    struct MockUserService {
        store_service: Arc<MockExtensionStoreService>,
        role_service: Arc<MockRoleService>,
        config_service: Arc<ConfigService>,
    }
    
    impl MockUserService {
        fn new(
            store_service: Arc<MockExtensionStoreService>,
            role_service: Arc<MockRoleService>,
            config_service: Arc<ConfigService>,
        ) -> Self {
            Self {
                store_service,
                role_service,
                config_service,
            }
        }
        
        fn get_server_name(&self) -> &str {
            &self.config_service.config().server.name
        }
    }
    
    #[derive(Debug)]
    struct TestSingletonService {
        name: String,
    }
    
    impl TestSingletonService {
        fn new(name: &str) -> Self {
            Self {
                name: name.to_string(),
            }
        }
    }
    
    #[derive(Debug)]
    struct TestTransientService {
        name: String,
    }
    
    impl TestTransientService {
        fn new(name: &str) -> Self {
            Self {
                name: name.to_string(),
            }
        }
    }
}
